﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using TfsComLib.Common;
using TfsComLib.TfsBranchLib2;
using WpfAdvControls.Component;

namespace TfsBranchLib2.Model
{
    public class SelectedBranchesCache : ComponentBase, ISelectedBranchesCache
    {
        private ObservableCollection<BranchData> branches;

        private ISourceBranches sourceBranchesProvider;

        public SelectedBranchesCache()
        {
            branches = new ObservableCollection<BranchData>();
        }

        public ISourceBranches SourceBranchesProvider
        {
            get { return sourceBranchesProvider; }
            set
            {
                sourceBranchesProvider = value;
                sourceBranchesProvider.PropertyChanged += sourceBranchesProvider_PropertyChanged;
                NotifyPropertyChanged("SourceBranchProvider");
            }
        }

        public ObservableCollection<BranchData> Branches
        {
            get { return branches; }
            set
            {
                branches = value;
                NotifyPropertyChanged("Branches");
            }
        }

        /// <summary>
        ///     Refresh list of branch from TFS, selected branches presisted
        /// </summary>
        public void Refresh()
        {
            if (sourceBranchesProvider == null)
            {
                var err = "Source Branch Provider is null";
                SetError(err);
                throw new TfsToolException(err);
            }
            try
            {
                var newBranchList = sourceBranchesProvider.GetBranchList();
                if ((newBranchList == null) || (newBranchList.Count == 0))
                    throw new TfsToolException("Branch list is empty");
                var serverPathComparer = BranchData.GetBranchDataComparer();
                var branchesToRemove = new List<BranchData>(branches.Except(newBranchList, serverPathComparer));
                foreach (var branch in branchesToRemove)
                {
                    branches.Remove(branch);
                }
                var newestBranches = new List<BranchData>(newBranchList.Except(branches, serverPathComparer));
                foreach (var branch in newestBranches)
                {
                    branches.Add(branch);
                }
            }
            catch (Exception ex)
            {
                SetError(ex);
                throw new TfsToolException("Error refreshing branch list", ex);
            }
            if (OnRefresh != null)
            {
                OnRefresh(this, null);
            }
        }

        public event EventHandler OnRefresh;

        public BranchData FindInPath(string newPath)
        {
            var query = from branch in branches
                where isIt(branch, newPath)
                select branch;
            var result = query.FirstOrDefault();
            return result;
        }

        public bool SetDefaultBranchForPath(string newPath, out BranchData branchOfPath)
        {
            branchOfPath = FindInPath(newPath);
            foreach (var branch in Branches)
            {
                branch.IsSelected = false;
            }
            branchOfPath.IsSelected = true;
            if (OnRefresh != null)
            {
                OnRefresh(this, null);
            }
            return true;
        }


        public void SetRecentBranches(List<BranchData> list)
        {
            var selNames = (from br in list select br.ServerPath).ToList();
            var setSelected = (from br in branches where selNames.Contains(br.ServerPath) select br).ToList();
            setSelected.ForEach(br => br.IsSelected = true);
            var setUnselected = (from br in branches where !selNames.Contains(br.ServerPath) select br).ToList();
            setUnselected.ForEach(br => br.IsSelected = false);
            if (OnRefresh != null)
            {
                OnRefresh(this, null);
            }
        }


        public void DoRefresh()
        {
            if (OnRefresh != null)
            {
                OnRefresh(this, null);
            }
        }

        private void sourceBranchesProvider_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "BasePath")
            {
                Refresh();
            }
        }


        private bool isIt(BranchData br, string path)
        {
            if (path.Contains(br.ServerPath))
            {
                if (path.Length == br.ServerPath.Length)
                {
                    return true;
                }
                if (path.Contains(br.ServerPath + "/"))
                {
                    return true;
                }
                return false;
            }
            return false;
        }
    }
}